﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace NoteHelper.Utils
{
    public enum InheritType
    {
        Form,
        Docking
    }

    public class BaseFormBuilder
    {
        public BaseFormBuilder()
        {
            DataGridName = "displayGrid";
            SplitContainer = "splitContainer1";
            ToolStrip = "toolStrip1";
            FormWidth = 500;
            FormHeight = 400;
        }

        private const string NEWLINE = "\r\n";
        private string[] nameToolStripButtons = new[] { "InsertToolStripButton", "EditToolStripButton", "RemoveToolStripButton", "CopyToolStripButton", "QueryToolStripButton", "toolStripSeparator1", "AcceptToolStripButton", "CancelToolStripButton", "toolStripSeparator", "PrintToolStripButton", "HelpToolStripButton" };
        private string[] textToolStripButtons = new[] { "添加", "修改", "删除", "复制", "查询", "|", "确定", "取消", "|", "打印", "帮助" };
        private string[] clickEvents = new[] { "InsertButtonClick", "EditButtonClick", "RemoveButtonClick", "CopyButtonClick", "QueryButtonClick", "", "AcceptButtonClick", "CancelButtonClick", "", "PrintButtonClick", "HelpButtonClick" };

        [Description("窗体的命名空间")]
        public string FormNameSpace { get; set; }

        [Description("窗体的类名")]
        public string FormClassName { get; set; }

        [Description("窗体的Text")]
        public string FromText { get; set; }

        [Description("文件输出路径")]
        public string OutputPath { get; set; }

        [DefaultValue(InheritType.Form)]
        public InheritType FormType { get; set; }

        public string DataGridName { get; set; }

        public string SplitContainer { get; set; }

        public string ToolStrip { get; set; }

        public int FormWidth { get; set; }

        public int FormHeight { get; set; }

        [Description("显示字段")]
        public string[] DisplayTitles { get; set; }

        [Description("数据字段")]
        public string[] DataFields { get; set; }

        public List<string> CheckErrors()
        {
            var errList = new List<string>();
            if (DisplayTitles == null || DisplayTitles.Length == 0)
                errList.Add("显示字段");
            if (DataFields == null || DataFields.Length == 0)
                errList.Add("数据字段");
            if (DataFields.Length != DisplayTitles.Length)
                errList.Add("显示字段与数据字段的长度不一致");
            if (string.IsNullOrWhiteSpace(FormClassName))
            {
                errList.Add("窗体的类名为必填项！");
            }
            return errList;
        }

        public void Generate()
        {
            var classFile = System.IO.Path.Combine(OutputPath, string.Format("{0}.cs", FormClassName));
            IOHelper.WriteFile(classFile, BuildFormClass());

            var dsignerFile = System.IO.Path.Combine(OutputPath, string.Format("{0}.Designer.cs", FormClassName));
            IOHelper.WriteFile(dsignerFile, BuildDesigner());

            var controllerFile = System.IO.Path.Combine(OutputPath, string.Format("{0}Controller.cs", FormClassName));
            IOHelper.WriteFile(controllerFile, BuildController());
        }

        private string GetFormType()
        {
            if (FormType == InheritType.Docking)
            {
                return "WeifenLuo.WinFormsUI.Docking.DockContent,IBaseView";
            }

            return "Form,IBaseView";
        }

        private string GetTab(int num, string ctx)
        {
            var tab = new StringBuilder();
            for (int i = 0; i < num; i++)
            {
                tab.Append("\t");
            }
            tab.Append(ctx);
            tab.Append(NEWLINE);
            return tab.ToString();
        }

        private string BuildFormClass()
        {
            var ctx = new StringBuilder();
            ctx.Append(GetTab(0, "using NoteHelper.Utils;"));
            ctx.Append(GetTab(0, "using System;"));
            ctx.Append(GetTab(0, "using System.Collections;"));
            ctx.Append(GetTab(0, "using System.Collections.Generic;"));
            ctx.Append(GetTab(0, "using System.ComponentModel;"));
            ctx.Append(GetTab(0, "using System.Data;"));
            ctx.Append(GetTab(0, "using System.Drawing;"));
            ctx.Append(GetTab(0, "using System.Linq;"));
            ctx.Append(GetTab(0, "using System.Text;"));
            ctx.Append(GetTab(0, "using System.Windows.Forms;"));
            ctx.Append(NEWLINE);
            ctx.Append(GetTab(0, string.Format("namespace {0}", FormNameSpace)));
            ctx.Append(GetTab(0, "{"));

            var className = string.Format("public partial class {0} : {1}", FormClassName, GetFormType());
            ctx.Append(GetTab(1, className));
            ctx.Append(GetTab(1, "{"));

            ctx.Append(GetTab(2, "private const string Pre = \"Data_\";"));
            ctx.Append(GetTab(2, "private log4net.ILog logger;"));
            ctx.Append(GetTab(2, "private DevAge.ComponentModel.IBoundList bd;"));
            ctx.Append(GetTab(2, string.Format("public {0}()", FormClassName)));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "InitializeComponent();"));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(NEWLINE);

            ctx.Append(GetTab(2, string.Format("private void {0}_Load(object sender, EventArgs e)", FormClassName)));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, string.Format("logger = log4net.LogManager.GetLogger(\"{0}.{1}\");", FormNameSpace, FormClassName)));
            ctx.Append(GetTab(3, string.Format("{0}.FixedRows = 1;", DataGridName)));
            ctx.Append(GetTab(3, string.Format("{0}.FixedColumns = 1;", DataGridName)));
            ctx.Append(GetTab(3, "CreateColumns();"));
            ctx.Append(GetTab(3, string.Format("var controller = new {0}Controller(this);", FormClassName)));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "private void CreateColumns()"));
            ctx.Append(GetTab(2, "{"));
            int count = DisplayTitles.Length;
            ctx.Append(GetTab(3, "SourceGrid.DataGridColumn gridColumn;"));
            for (int i = 0; i < count; i++)
            {
                ctx.Append(GetTab(3, string.Format("gridColumn = {0}.Columns.Add(\"{1}\", \"{2}\", typeof(string));",
                                        DataGridName, DataFields[i], DisplayTitles[i])));
                ctx.Append(GetTab(3, "gridColumn.Width = 100;"));
            }
            ctx.Append(GetTab(2, "}"));
            GenrateIBaseViewImpl(ctx);

            ctx.Append(NEWLINE);
            ctx.Append(GetTab(2, "#region ==== Toolbar Event ===="));
            count = clickEvents.Length;
            for (int i = 0; i < count; i++)
            {
                if (!string.IsNullOrEmpty(clickEvents[i]))
                {
                    var eventName = clickEvents[i].Replace("ButtonClick", "?.Invoke(sender, e);");
                    var clickMethod = CreateEventMethod(clickEvents[i], textToolStripButtons[i], eventName, true);
                    ctx.Append(clickMethod);
                }
            }
            ctx.Append(GetTab(2, "#endregion"));

            ctx.Append(GetTab(1, "}"));

            ctx.Append(GetTab(0, "}"));

            return ctx.ToString();
        }

        private void GenrateIBaseViewImpl(StringBuilder ctx)
        {
            ctx.Append(GetTab(2, "#region ==== IBaseView Impl ===="));
            ctx.Append(NEWLINE);
            ctx.Append(GetTab(2, "private DataTable _displayList;"));
            ctx.Append(GetTab(2, "public DataTable DisplayList"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "get { return _displayList; }"));
            ctx.Append(GetTab(3, "set"));
            ctx.Append(GetTab(3, "{"));
            ctx.Append(GetTab(4, "if (value == null) return;"));
            ctx.Append(GetTab(4, "_displayList = value;"));
            ctx.Append(GetTab(4, ""));
            ctx.Append(GetTab(4, "bd = new DevAge.ComponentModel.BoundDataView(_displayList.DefaultView);"));
            ctx.Append(GetTab(4, "bd.AllowNew = false;"));
            ctx.Append(GetTab(4, "bd.AllowEdit = false;"));
            ctx.Append(GetTab(4, "bd.AllowDelete = false;"));
            ctx.Append(GetTab(4, string.Format("{0}.DataSource = bd;", DataGridName)));
            ctx.Append(GetTab(3, "}"));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "public FormCommand Cmd { get; set; }"));
            ctx.Append(GetTab(2, "public Hashtable RowData"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "get"));
            ctx.Append(GetTab(3, "{"));
            ctx.Append(GetTab(4, string.Format("return {0}.Panel1.GetData(Pre);", SplitContainer)));
            ctx.Append(GetTab(3, "}"));
            ctx.Append(GetTab(3, "set"));
            ctx.Append(GetTab(3, "{"));
            ctx.Append(GetTab(4, string.Format("{0}.Panel1.SetData(Pre, value);", SplitContainer)));
            ctx.Append(GetTab(3, "}"));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "public event EventHandler Insert;"));
            ctx.Append(GetTab(2, "public event EventHandler Edit;"));
            ctx.Append(GetTab(2, "public event EventHandler Remove;"));
            ctx.Append(GetTab(2, "public event EventHandler Copy;"));
            ctx.Append(GetTab(2, "public event EventHandler Query;"));
            ctx.Append(GetTab(2, "public event EventHandler Accept;"));
            ctx.Append(GetTab(2, "public event EventHandler Cancel;"));
            ctx.Append(GetTab(2, "public event EventHandler Print;"));
            ctx.Append(GetTab(2, "public event EventHandler Help;"));
            ctx.Append(GetTab(2, "public void BeginEdit()"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, string.Format("{0}.Panel1.ChangeInputState(Pre, true);", SplitContainer)));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "public void EndEdit()"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, string.Format("{0}.Panel1.ChangeInputState(Pre, false);", SplitContainer)));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "public int GetRowIndex()"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "int rowIndex = -1;"));
            ctx.Append(GetTab(3, "object[] rows = displayGrid.SelectedDataRows;"));
            ctx.Append(GetTab(3, "if (rows != null && rows.Length > 0)"));
            ctx.Append(GetTab(3, "{"));
            ctx.Append(GetTab(4, "DataRowView row = (DataRowView)rows[0];"));
            ctx.Append(GetTab(4, "int.TryParse(row[\"$_rowIndex\"].ToString(), out rowIndex);"));
            ctx.Append(GetTab(3, "}"));
            ctx.Append(GetTab(3, "return rowIndex;"));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(NEWLINE);
            ctx.Append(GetTab(2, "public void Notify(string notification)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "AlterMsg.Info(notification);"));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "#endregion"));
        }

        private string BuildDesigner()
        {
            var ctx = new StringBuilder();
            ctx.AppendFormat("namespace {0}", FormNameSpace);
            ctx.Append(NEWLINE);
            ctx.Append("{");
            ctx.Append(NEWLINE);
            var formClassName = string.Format("partial class {0}", FormClassName);
            ctx.Append(GetTab(1, formClassName));
            ctx.Append(GetTab(1, "{"));
            ctx.Append(GetTab(2, "/// <summary>"));
            ctx.Append(GetTab(2, "/// 必需的设计器变量。"));
            ctx.Append(GetTab(2, "/// </summary>"));
            ctx.Append(GetTab(2, "private System.ComponentModel.IContainer components = null;"));
            ctx.Append(GetTab(0, ""));

            ctx.Append(GetTab(2, "/// <summary>"));
            ctx.Append(GetTab(2, "/// 清理所有正在使用的资源。"));
            ctx.Append(GetTab(2, "/// </summary>"));
            ctx.Append(GetTab(2, "/// <param name=\"disposing\">如果应释放托管资源，为 true；否则为 false。</param>"));
            ctx.Append(GetTab(2, "protected override void Dispose(bool disposing)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "if (disposing && (components != null))"));
            ctx.Append(GetTab(3, "{"));
            ctx.Append(GetTab(4, "components.Dispose();"));
            ctx.Append(GetTab(3, "}"));
            ctx.Append(GetTab(3, "base.Dispose(disposing);"));
            ctx.Append(GetTab(2, "}"));

            #region ==== 窗体布局 ====

            ctx.Append(GetTab(0, ""));
            ctx.Append(GetTab(2, "#region Windows 窗体设计器生成的代码"));
            ctx.Append(GetTab(2, ""));
            ctx.Append(GetTab(2, "/// <summary>"));
            ctx.Append(GetTab(2, "/// 设计器支持所需的方法 - 不要修改"));
            ctx.Append(GetTab(2, "/// 使用代码编辑器修改此方法的内容。"));
            ctx.Append(GetTab(2, "/// </summary>"));
            ctx.Append(GetTab(2, "private void InitializeComponent()"));
            ctx.Append(GetTab(2, "{"));

            //
            // 实例化控件
            //
            ctx.Append(GetTab(3, string.Format("this.{0} = new System.Windows.Forms.ToolStrip();", ToolStrip)));
            int count = nameToolStripButtons.Length;
            for (int i = 0; i < count; i++)
            {
                var name = nameToolStripButtons[i];
                if (string.IsNullOrEmpty(clickEvents[i]))
                {
                    ctx.Append(GetTab(3, string.Format("this.{0} = new System.Windows.Forms.ToolStripSeparator();", name)));
                }
                else
                {
                    ctx.Append(GetTab(3, string.Format("this.{0} = new System.Windows.Forms.ToolStripButton();", name)));
                }
            }
            ctx.Append(GetTab(3, string.Format("this.{0} = new SourceGrid.DataGrid();", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0} = new System.Windows.Forms.SplitContainer();", SplitContainer)));

            //
            // 注意：先布局容器 begin
            //
            ctx.Append(GetTab(3, string.Format("this.{0}.SuspendLayout();", ToolStrip)));
            ctx.Append(GetTab(3, string.Format("((System.ComponentModel.ISupportInitialize)(this.{0})).BeginInit();", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Panel1.SuspendLayout();", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Panel2.SuspendLayout();", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.SuspendLayout();", SplitContainer)));
            ctx.Append(GetTab(3, "this.SuspendLayout();"));

            GenerateToolStrip(ctx);
            GenerateSpliteContainer(ctx);
            GenerateDataGrid(ctx);
            GenerateFormContent(ctx);
            //
            // 布局容器 end
            //
            ctx.Append(GetTab(3, string.Format("this.{0}.ResumeLayout(false);", ToolStrip)));
            ctx.Append(GetTab(3, string.Format("this.{0}.PerformLayout();", ToolStrip)));
            //ctx.Append(GetTab(3, string.Format("this.{0}.Panel1.ResumeLayout(false);", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Panel2.ResumeLayout(false);", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("((System.ComponentModel.ISupportInitialize)(this.{0})).EndInit();", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.ResumeLayout(false);", SplitContainer)));
            ctx.Append(GetTab(3, "this.ResumeLayout(false);"));
            ctx.Append(GetTab(3, "this.PerformLayout();"));// 窗体布局

            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, ""));
            ctx.Append(GetTab(2, "#endregion"));

            #endregion

            #region ==== 定义控件 ====

            ctx.Append(NEWLINE);
            ctx.Append(GetTab(2, string.Format("private System.Windows.Forms.ToolStrip {0};", ToolStrip)));
            for (int i = 0; i < count; i++)
            {
                var name = nameToolStripButtons[i];
                if (string.IsNullOrEmpty(clickEvents[i]))
                {
                    ctx.Append(GetTab(2, string.Format("private System.Windows.Forms.ToolStripSeparator {0};", name)));
                }
                else
                {
                    ctx.Append(GetTab(2, string.Format("private System.Windows.Forms.ToolStripButton {0};", name)));
                }
            }
            ctx.Append(GetTab(2, string.Format("private System.Windows.Forms.SplitContainer {0};", SplitContainer)));
            ctx.Append(GetTab(2, string.Format("private SourceGrid.DataGrid {0};", DataGridName)));

            #endregion

            ctx.Append(GetTab(1, "}"));
            ctx.Append(GetTab(0, "}"));

            return ctx.ToString();
        }

        private string BuildController()
        {
            var ctx = new StringBuilder();
            ctx.Append(GetTab(0, "using NoteHelper.Utils;"));
            ctx.Append(GetTab(0, "using System;"));
            ctx.Append(GetTab(0, "using System.Collections;"));
            ctx.Append(GetTab(0, "using System.Collections.Generic;"));
            ctx.Append(GetTab(0, "using System.Data;"));
            ctx.Append(GetTab(0, "using System.Linq;"));
            ctx.Append(GetTab(0, "using System.Text;"));
            ctx.Append(NEWLINE);
            ctx.Append(GetTab(0, string.Format("namespace {0}", FormNameSpace)));
            ctx.Append(GetTab(0, "{"));
            ctx.Append(GetTab(1, string.Format("public class {0}Controller", FormClassName)));
            ctx.Append(GetTab(1, "{"));
            ctx.Append(GetTab(2, "private int rowIndex;"));
            ctx.Append(GetTab(2, "private IBaseView view;"));
            ctx.Append(GetTab(2, string.Format("public {0}Controller(IBaseView baseView)", FormClassName)));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "view = baseView;"));
            ctx.Append(NEWLINE);
            ctx.Append(GetTab(3, "view.Insert += Form_Insert;"));
            ctx.Append(GetTab(3, "view.Edit += Form_Edit;"));
            ctx.Append(GetTab(3, "view.Remove += Form_Remove;"));
            ctx.Append(GetTab(3, "view.Copy += Form_Copy;"));
            ctx.Append(GetTab(3, "view.Query += Form_Query;"));
            ctx.Append(GetTab(3, "view.Accept += Form_Accept;"));
            ctx.Append(GetTab(3, "view.Cancel += Form_Cancel;"));
            ctx.Append(GetTab(3, "view.Print += Form_Print;"));
            ctx.Append(GetTab(3, "view.Help += Form_Help;"));
            ctx.Append(GetTab(2, "}"));

            ctx.Append(GetTab(2, "private void Form_Insert(object sender, EventArgs e)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "view.RowData = null;"));
            ctx.Append(GetTab(3, "view.Cmd = FormCommand.Insert;"));
            ctx.Append(GetTab(3, "view.BeginEdit();"));
            ctx.Append(GetTab(2, "}"));

            ctx.Append(GetTab(2, "private void Form_Edit(object sender, EventArgs e)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "BeginEdit(FormCommand.Edit);"));
            ctx.Append(GetTab(2, "}"));

            ctx.Append(GetTab(2, "private void Form_Remove(object sender, EventArgs e)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "Form_Cancel(null, null);"));
            ctx.Append(GetTab(3, "rowIndex = view.GetRowIndex();"));
            ctx.Append(GetTab(3, "if (rowIndex == -1) return;"));
            ctx.Append(NEWLINE);
            ctx.Append(GetTab(3, "var deleteRow = view.DisplayList.Rows[rowIndex];"));
            ctx.Append(GetTab(3, "view.DisplayList.Rows.RemoveAt(rowIndex);"));
            ctx.Append(GetTab(3, "for (int i = rowIndex; i < view.DisplayList.Rows.Count; i++)"));
            ctx.Append(GetTab(3, "{"));
            ctx.Append(GetTab(4, "var row = view.DisplayList.Rows[i];"));
            ctx.Append(GetTab(4, "row[\"$_rowIndex\"] = i;"));
            ctx.Append(GetTab(3, "}"));
            ctx.Append(GetTab(2, "}"));

            ctx.Append(GetTab(2, "private void Form_Copy(object sender, EventArgs e)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "BeginEdit(FormCommand.Insert);"));
            ctx.Append(GetTab(2, "}"));

            ctx.Append(GetTab(2, "private void BeginEdit(FormCommand cmd)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "rowIndex = view.GetRowIndex();"));
            ctx.Append(GetTab(3, "if (rowIndex == -1) return;"));
            ctx.Append(NEWLINE);
            ctx.Append(GetTab(3, "var selectedRow = view.DisplayList.Rows[rowIndex];"));
            ctx.Append(GetTab(3, "var ht = view.RowData;"));
            ctx.Append(GetTab(3, "ht.GetValueFormDataRow(selectedRow);"));
            ctx.Append(GetTab(3, "view.RowData = ht;"));
            ctx.Append(GetTab(3, "view.Cmd = cmd;"));
            ctx.Append(GetTab(3, "view.BeginEdit();"));
            ctx.Append(GetTab(2, "}"));

            ctx.Append(GetTab(2, "private void Form_Query(object sender, EventArgs e)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "view.RowData = null;"));
            ctx.Append(GetTab(3, "view.Cmd = FormCommand.Query;"));
            ctx.Append(GetTab(3, "view.BeginEdit();"));
            ctx.Append(GetTab(2, "}"));

            ctx.Append(GetTab(2, "private void Form_Accept(object sender, EventArgs e)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "bool error = false;"));
            ctx.Append(GetTab(3, "switch (view.Cmd)"));
            ctx.Append(GetTab(3, "{"));
            ctx.Append(GetTab(4, "case FormCommand.Display:"));
            ctx.Append(GetTab(5, "break;"));
            ctx.Append(GetTab(4, "case FormCommand.Insert:"));
            ctx.Append(GetTab(5, "//实例化var insertEntity = new Model.ProjectForm();"));
            ctx.Append(GetTab(5, "// 填充数据"));
            ctx.Append(GetTab(5, "//view.RowData.FillValueToEntity(insertEntity);"));
            ctx.Append(GetTab(5, "// 更新数据库"));
            ctx.Append(GetTab(5, "var insertRow = view.DisplayList.NewRow();"));
            ctx.Append(GetTab(5, "// 填充数据到insertRow;"));
            ctx.Append(GetTab(5, "insertRow[\"$_rowIndex\"] = view.DisplayList.Rows.Count;"));
            ctx.Append(GetTab(5, "view.DisplayList.Rows.Add(insertRow);"));
            ctx.Append(GetTab(5, "break;"));
            ctx.Append(GetTab(4, "case FormCommand.Edit:"));
            ctx.Append(GetTab(5, "var editRow = view.DisplayList.Rows[rowIndex];"));
            ctx.Append(GetTab(5, "var id = editRow[\"ObjectID\"];"));
            ctx.Append(GetTab(5, "break;"));
            ctx.Append(GetTab(4, "case FormCommand.Query:"));
            ctx.Append(GetTab(5, "Query(view.RowData);"));
            ctx.Append(GetTab(5, "break;"));
            ctx.Append(GetTab(4, "default:"));
            ctx.Append(GetTab(5, "break;"));
            ctx.Append(GetTab(3, "}"));
            ctx.Append(GetTab(3, "if (error) return;"));
            ctx.Append(GetTab(3, "view.RowData = null;"));
            ctx.Append(GetTab(3, "view.Cmd = FormCommand.Display;"));
            ctx.Append(GetTab(3, "view.EndEdit();"));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "private void Query(Hashtable ht)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "// 查询数据库"));
            ctx.Append(GetTab(3, "var table = new DataTable();"));
            ctx.Append(GetTab(3, "view.DisplayList = table;"));
            ctx.Append(GetTab(2, "}"));
            ctx.Append(GetTab(2, "private void Form_Cancel(object sender, EventArgs e)"));
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, "view.RowData = null;"));
            ctx.Append(GetTab(3, "view.Cmd = FormCommand.Display;"));
            ctx.Append(GetTab(3, "view.EndEdit();"));
            ctx.Append(GetTab(2, "}"));
            var Print = CreateEventMethod("Form_Print", "", "throw new NotImplementedException();", true);
            ctx.Append(Print);
            var Help = CreateEventMethod("Form_Help", "", "throw new NotImplementedException();", true);
            ctx.Append(Help);

            ctx.Append(GetTab(1, "}"));
            ctx.Append(GetTab(0, "}"));

            return ctx.ToString();
        }

        private void GenerateDataGrid(StringBuilder ctx)
        {
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("// {0}", DataGridName)));
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("this.{0}.DeleteQuestionMessage = \"您确定要删除所有选中的记录? \";", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Dock = System.Windows.Forms.DockStyle.Fill;", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0}.EnableSort = false;", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0}.FixedRows = 1;", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Location = new System.Drawing.Point(0, 0);", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Name = \"{0}\";", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0}.SelectionMode = SourceGrid.GridSelectionMode.Row;", DataGridName)));
            ctx.Append(GetTab(3, string.Format("this.{0}.TabStop = true;", DataGridName)));

        }

        private void GenerateSpliteContainer(StringBuilder ctx)
        {
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("// {0}", SplitContainer)));
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("this.{0}.Dock = System.Windows.Forms.DockStyle.Fill;", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.IsSplitterFixed = true;", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Location = new System.Drawing.Point(0, 25);", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Name = \"{0}\";", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Orientation = System.Windows.Forms.Orientation.Horizontal;", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Size = new System.Drawing.Size({1}, {2});", SplitContainer, FormWidth, FormHeight - 25)));
            ctx.Append(GetTab(3, string.Format("this.{0}.SplitterDistance = 117;", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.{0}.TabIndex = 1;", SplitContainer)));

            //ctx.Append(GetTab(3, "//"));
            //ctx.Append(GetTab(3, string.Format("// {0}.Panel1", SplitContainer)));
            //ctx.Append(GetTab(3, "//"));
            //ctx.Append(GetTab(3, string.Format("this.{0}.Panel1.Controls.Add(this.panel1);", SplitContainer)));
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("// {0}.Panel2", SplitContainer)));
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("this.{0}.Panel2.Controls.Add(this.{1});", SplitContainer, DataGridName)));
        }

        private void GenerateToolStrip(StringBuilder ctx)
        {
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("// {0}", ToolStrip)));
            ctx.Append(GetTab(3, "//"));
            var children = string.Format("this.{0}.Items.AddRange(new System.Windows.Forms.ToolStripItem[]", ToolStrip);
            ctx.Append(GetTab(3, children + " {"));
            int count = nameToolStripButtons.Length;
            for (int i = 0; i < count; i++)
            {
                var button = string.Format("this.{0}", nameToolStripButtons[i]);
                if (i < count - 1)
                    button += ",";
                ctx.Append(GetTab(4, button));
            }

            ctx.Append(GetTab(3, "});"));
            ctx.Append(GetTab(3, string.Format("this.{0}.Location = new System.Drawing.Point(0, 0);", ToolStrip)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Size = new System.Drawing.Size({1}, 25);", ToolStrip, FormWidth)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Name = \"{0}\";", ToolStrip)));
            ctx.Append(GetTab(3, string.Format("this.{0}.Text = \"{0}\";", ToolStrip)));
            ctx.Append(GetTab(3, string.Format("this.{0}.TabIndex = 0;", ToolStrip)));

            for (int i = 0; i < count; i++)
            {
                var button = GenerateToolStripButton(nameToolStripButtons[i], textToolStripButtons[i], clickEvents[i]);
                ctx.Append(button);
            }
        }

        /// <summary>
        /// 生成窗体属性
        /// </summary>
        /// <param name="ctx"></param>
        private void GenerateFormContent(StringBuilder ctx)
        {
            // 固定项
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("// {0}", FormClassName)));
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, "this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);"));
            ctx.Append(GetTab(3, "this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;"));

            // Form大小
            if (FormWidth > 0 && FormHeight > 0)
            {
                ctx.Append(GetTab(3, string.Format("this.ClientSize = new System.Drawing.Size({0}, {1});", FormWidth, FormHeight)));
            }

            // 直接添加到Form上的控件
            ctx.Append(GetTab(3, string.Format("this.Controls.Add(this.{0});", SplitContainer)));
            ctx.Append(GetTab(3, string.Format("this.Controls.Add(this.{0});", ToolStrip)));
            
            ctx.Append(GetTab(3, string.Format("this.Name = \"{0}\";", FormClassName)));
            var formText = string.Format("this.Text = \"{0}\";", string.IsNullOrEmpty(FromText) ? FormClassName : FromText);
            ctx.Append(GetTab(3, formText));
            ctx.Append(GetTab(3, string.Format("this.Load += new System.EventHandler(this.{0}_Load);", FormClassName)));
        }

        private string GenerateToolStripButton(string name, string text, string eventName)
        {
            var ctx = new StringBuilder();
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("// {0}", name)));
            ctx.Append(GetTab(3, "//"));
            ctx.Append(GetTab(3, string.Format("this.{0}.Name = \"{0}\";", name)));
            if (string.IsNullOrEmpty(eventName))
            {
                ctx.Append(GetTab(3, string.Format("this.{0}.Size = new System.Drawing.Size(6, 25);", name)));
            }
            else
            {
                ctx.Append(GetTab(3, string.Format("this.{0}.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;", name)));
                ctx.Append(GetTab(3, string.Format("this.{0}.Image = global::NoteHelper.GlobalResource.{1}ToolStripButton_Image;", name, text)));
                ctx.Append(GetTab(3, string.Format("this.{0}.ImageTransparentColor = System.Drawing.Color.Magenta;", name)));
                ctx.Append(GetTab(3, string.Format("this.{0}.Text = \"{1}\";", name, text)));
                ctx.Append(GetTab(3, string.Format("this.{0}.Size = new System.Drawing.Size(23, 22);", name)));
                ctx.Append(GetTab(3, string.Format("this.{0}.Click += new System.EventHandler(this.{1});", name, eventName)));
            }

            return ctx.ToString();
        }

        private string CreateEventMethod(string name, string description, string code, bool isPrivate)
        {
            var ctx = new StringBuilder();
            if (!string.IsNullOrEmpty(description))
            {
                ctx.Append(GetTab(2, "/// <summary>"));
                ctx.Append(GetTab(2, string.Format("/// {0}", description)));
                ctx.Append(GetTab(2, "/// </summary>"));
            }
            if (isPrivate)
            {
                ctx.Append(GetTab(2, string.Format("private void {0}(object sender, EventArgs e)", name)));
            }
            else
            {
                ctx.Append(GetTab(2, string.Format("public void {0}(object sender, EventArgs e)", name)));
            }
            ctx.Append(GetTab(2, "{"));
            ctx.Append(GetTab(3, code));
            ctx.Append(GetTab(2, "}"));

            return ctx.ToString();
        }
    }
}
